package cn.bearspark.file.provider.service.impl;

import cn.bearspark.common.enumeration.ModuleEnum;
import cn.bearspark.file.provider.dao.mapper.UsefulFileMapper;
import cn.bearspark.file.provider.service.FileService;
import cn.bearspark.schedule.rpc.ScheduleRpc;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;

import static cn.bearspark.common.constant.GlobalConstant.BASE_DIR;

/**
 * @author f
 */
@Service
@EnableScheduling
public class FileServiceImpl implements FileService {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileServiceImpl.class);

    @DubboReference
    private ScheduleRpc scheduleRpc;

    private final UsefulFileMapper usefulFileMapper;

    public FileServiceImpl(UsefulFileMapper usefulFileMapper) {
        this.usefulFileMapper = usefulFileMapper;
    }

    @Override
    public void prepareDeletion(String filename, int moduleCode) {
        LocalDateTime deadline;
        LocalDateTime now = LocalDateTime.now();
        if (moduleCode == ModuleEnum.HAPPENING.getCode()) {
            // 如果是动态模块的图片，过期时间是 30min
            deadline = now.plusMinutes(30);
        } else if (moduleCode == ModuleEnum.ARTICLE.getCode()) {
            // 如果是专栏模块的图片，过期时间是 1d
            deadline = now.plusDays(1);
        } else {
            throw new RuntimeException("unsupported module code: " + moduleCode);
        }
        scheduleRpc.scheduled(ModuleEnum.FILE.getCode(), deadline, filename);
    }

    @Override
    public void preventDeletion(List<String> urlList) {
        usefulFileMapper.insertBatch(getFilenameList(urlList));
    }

    // 获取路径中文件名
    private static List<String> getFilenameList(List<String> urlList) {
        return urlList.stream().map(url -> url.substring(url.lastIndexOf("/") + 1)).toList();
    }

    @Override
    public void onFileDeadline(List<String> filenameList) {
        Set<String> usefulFilenameSet = usefulFileMapper.getUsefulFilenameSet(filenameList);
        filenameList.stream()
                .filter(filename -> !usefulFilenameSet.contains(filename))
                .forEach(filename -> {
                    // 如果文件没有被使用，则删除本地存储的图片
                    try {
                        Files.deleteIfExists(Paths.get(BASE_DIR).resolve(filename).normalize());
                    } catch (IOException e) {
                        LOGGER.error("delete error", e);
                    }
                });
    }

    @Override
    public void deleteBatch(List<String> urlList) {
        List<String> filenameList = getFilenameList(urlList);
        usefulFileMapper.deleteBatch(filenameList);
        filenameList.forEach(filename -> {
            try {
                Files.deleteIfExists(Paths.get(BASE_DIR).resolve(filename).normalize());
            } catch (IOException e) {
                LOGGER.error("delete error", e);
            }
        });
    }

    /**
     * 每天 0点0分，清理在数据库中存储超过一天的文件名
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void deleteBeyondDay() {
        usefulFileMapper.deleteBeyondDay(LocalDateTime.now().minusDays(1));
    }
}
